﻿/// <reference path="jquery-1.4.4-vsdoc.js" />
/// <reference path="json2.js" />

var mapFabric = function (element, data) {
    this.x = 0;
    this.y = 0;
    this.element = element;
    this.controls = {};

    var id = 0;
    var genId = function () { return "i" + id++; }

    // init
    element.data("object", this);

    this.add = function (control) {
        if (control.id == undefined) control.id = genId();
        this.controls[control.id] = control;
        element.append(control.element);
        control.element.data("object", control);
        control.draw();
    }

    if (data != null) {
        for (var id in data) {
            var item = new itemFabric(this, data[id], null, null, { x: 0, y: 0 });            
        }
    }

    this.moveAdd = function (xp, yp) {
        if (this.x - xp > 0) xp = 0;
        if (this.x - xp < -1599 + 600) xp = 0;
        if (this.y - yp > 0) yp = 0;
        if (this.y - yp < -1537 + 600) yp = 0;

        this.x -= xp;
        this.y -= yp;

        this.draw();
    }

    this.draw = function () {
        element.css({
            "background-position-x": this.x + "px",
            "background-position-y": this.y + "px"
        });

        for (var id in this.controls) {
            this.controls[id].draw();
        }
    }

    this.getObjectByElement = function (element) {
        return element.data("object");
    }



    this.remove = function (control) {
        delete this.controls[control.id];
        control.element.remove();
    }

    this.getCenter = function () {
        return {
            x: -1 * this.x + 300,
            y: -1 * this.y + 300
        };
    }

    this.saveState = function () {
        var result = {
            x: this.x,
            y: this.y
        };

        for (var id in this.controls) {
            result[id] = this.controls[id].saveState();
        }

        return result;
    }

    this.loadState = function (state, duration, oncomplete) {
        var numberOfWait = 1;
        var wait = function () {
            if (--numberOfWait == 0) {
                oncomplete();
            }
        };

        for (var id in this.controls) {
            if (state[id] != undefined) {
                numberOfWait++;
            }
        }

        for (var id in this.controls) {
            if (state[id] != undefined) {
                this.controls[id].loadState(state[id], duration, wait);
            }
        }

        $(this).animate({ x: state.x, y: state.y }, {
            step: function (now, fx) {
                if (fx.prop == "x") this.x = now; else this.y = now;
                this.draw();
            },
            complete: wait,
            duration: duration
        });
    }

    this.selected = null;
    this.select = function (control) {
        if (this.selected != null) {
            this.selected.element.removeClass("selected")
        }
        this.selected = control;
        this.selected.element.addClass("selected");
        this.controller.canAttack(true);
    }

    this.onClick = function () {
        if (this.selected != null) {
            this.selected.element.removeClass("selected")
        }
        this.selected = null;
        this.controller.canAttack(false);
    }

    this.pack = function () {
        var result = {};
        for (var id in this.controls) {
            result[id] = this.controls[id].pack();
        }
        return result;
    }
}

var shoot = function (map, x1, y1, x2, y2, completed) {
    this.x = x1 + 13;
    this.y = y1 + 13;

    this.element = $("<img src='/Content/bullet.png' style='position:absolute;'/>")
        .css({left:x1+13,top:x1+13})
        .appendTo(map.element);

    this.draw = function () {
        this.element.css({
            left: (map.x + this.x).toString() + "px",
            top: (map.y + this.y).toString() + "px"
        });
    }

    $(this).animate({ x: x2, y: y2 }, {
        step: function (now, fx) {
            if (fx.prop == "x") this.x = now; else this.y = now;
            this.draw();
        },
        complete: function () {
            this.element.remove();
            if (completed != null) completed();
        },
        duration: "fast"
    });
}

var itemFabric = function (map, data, heroId, src, point) {
    this.x = point.x;
    this.y = point.y;
    this.heroId = data != null ? data.heroId : heroId;
    this.src = data != null ? data.src : src;
    this.attackPos = null;
    if (data != null) this.id = data.id;

    this.element = $("<img class='hero' style='width:32px;height:32px;position:absolute;' />")
        .attr("src", this.src);

    this.draw = function () {
        this.element.css({
            left: (map.x + this.x).toString() + "px",
            top: (map.y + this.y).toString() + "px"
        });
    }

    this.moveAdd = function (xp, yp) {
        this.x -= xp;
        this.y -= yp;

        this.draw();
    }

    this.saveState = function () {
        return {
            x: this.x,
            y: this.y,
            attackPos: this.attackPos
        };
    }

    this.loadState = function (state, duration, oncomplete) {
        var numberOfWait = 1;
        var wait = function () {
            if (--numberOfWait == 0) {
                oncomplete();
            }
        };

        this.attackPos = state.attackPos;

        if (duration !== 100 && this.attackPos != null) {
            numberOfWait += 1;
            new shoot(map, this.x, this.y, this.attackPos.x, this.attackPos.y, wait);
        }

        $(this).animate({ x: state.x, y: state.y }, {
            step: function (now, fx) {
                if (fx.prop == "x") this.x = now; else this.y = now;
                this.draw();
            },
            complete: wait,
            duration: duration
        });
    }

    this.onClick = function () {
        map.select(this);
    }

    this.attack = function (x, y) {
        this.attackPos = { x: x, y: y };
    }

    this.noattack = function () {
        this.attackPos = null;
    }

    this.pack = function () {
        return {
            id: this.id,
            heroId: this.heroId,
            src: this.src
        };
    }

    map.add(this);
}

var controllerFabric = function (map) {
    var isMoved = false;
    var item = null;
    var xb = 0;
    var yb = 0;

    var isAttack = false;

    // init
    map.element.mousedown(function (e) {
        item = map.getObjectByElement($(e.srcElement));

        if (item != undefined) {

            if (!isAttack) {
                isMoved = true;
                xb = e.clientX;
                yb = e.clientY;
                return false;
            } else {
                $("#message").text("");
                isAttack = false;
                map.selected.attack(e.pageX - map.element.offset().left - map.x, e.pageY - map.element.offset().top - map.y);

                map.timeline.disabled();
                new shoot(map, map.selected.x, map.selected.y, map.selected.attackPos.x, map.selected.attackPos.y, function () {
                    map.timeline.enabled();
                });
                return false;
            }
        }
    }).mousemove(function (e) {
        if (isMoved) {
            map.element.css({ cursor: "move" });
            xp = xb - e.clientX;
            yp = yb - e.clientY;

            item.moveAdd(xp, yp);

            xb = e.clientX;
            yb = e.clientY;
        }
    })
    .mouseup(function () {
        isMoved = false;
        map.element.css({ cursor: "default" });
        if (item.onClick != undefined) {
            item.onClick();
        }
    });

    $("#attack").click(function () {
        isAttack = true;
        $("#message").text("Укажите, куда атаковать");
        map.element.css("cursor", "crosshair");
    });

    $("#noattack").click(function () {
        if (map.selected != null) map.selected.noattack();
    });

    this.canAttack = function (can) {
        if (can) $("#attack").removeAttr("disabled"); else $("#attack").attr("disabled", "disabled");
        if (can) $("#noattack").removeAttr("disabled"); else $("#noattack").attr("disabled", "disabled");
    }

    this.canAttack(false);
}

var timelineFabric = function (map, data) {
    var current = 0;
    var steps = data || [];

    if (steps.length == 0) {
        steps.push(null);
    }

    var currentStepElement = $("#currentStep");
    currentStepElement.text(current);

    var saveStep = function () {
        var state = {};
        state["map"] = map.saveState();
        return state;
    }

    this.disabled = function () {
        $("#prev").attr('disabled', 'disabled');
        $("#next").attr('disabled', 'disabled');
        $("#play").attr('disabled', 'disabled');
        $("#clear").attr('disabled', 'disabled');
        $("#toBegin").attr('disabled', 'disabled');
        $("#toFinish").attr('disabled', 'disabled');
    }

    this.enabled = function () {
        $("#prev").removeAttr('disabled');
        $("#next").removeAttr('disabled');
        $("#play").removeAttr('disabled');
        $("#clear").removeAttr('disabled');
        $("#toBegin").removeAttr('disabled');
        $("#toFinish").removeAttr('disabled');
    }
    var self = this;
    var loadStep = function (state, duration, oncomplete) {
        self.disabled();

        map.loadState(state.map, duration, function () {
            self.enabled();
            if (oncomplete != null) oncomplete();
        });
    }

    this.next = function () {
        var state = saveStep();
        steps[current] = state;
        current += 1;
        if (data != null && current >= steps.length - 1) current = steps.length - 1;
        if (data == null && steps.length <= current) {
            steps.push(state);
        }
        currentStepElement.text(current);
        loadStep(steps[current], "fast");
    }

    this.prev = function () {
        steps[current] = saveStep();
        current -= 1;

        if (current >= 0) {
            currentStepElement.text(current);
            loadStep(steps[current], "fast", null);
        } else {
            current = 0;
        }

    }

    var isplaying = false;

    this.play = function () {
        steps[current] = saveStep();
        current = -1;
        isplaying = true;

        var next = null;
        next = function () {
            if (isplaying && current < steps.length - 1) {
                current++;
                loadStep(steps[current], 3000, next);
                currentStepElement.text(current);
            } else {
                isplaying = false;
                currentStepElement.text(current);
            }

        }

        loadStep(steps[0], 100, next);
    }

    this.stop = function () {
        isplaying = false;
        $(map).stop(false, true);
        for (var i = 0; i < map.controls.length; i++) {
            $(map.controls[i]).stop(false, true);
        }
    }

    $("#prev").click(this.prev);
    $("#next").click(this.next);
    $("#play").click(this.play);
    $("#clear").click(function () {
        current = 0;
        currentStepElement.text(current);
        steps = [];
        steps.push(null);
    });
    $("#stop").click(this.stop);
    $("#toBegin").click(function () {
        steps[current] = saveStep();
        current = 0;
        currentStepElement.text(current);
        loadStep(steps[current], "fast", null);
        
    });
    $("#toFinish").click(function () {
        steps[current] = saveStep();
        current = steps.length - 1;
        currentStepElement.text(current);
        loadStep(steps[current], "fast", null);
        
    });

    this.pack = function () {
        steps[current] = saveStep();
        return steps;
    }

    if (data != null) {
        loadStep(steps[0], 100, null);
    }
}



$(function () {
    $("#dialog").dialog({ autoOpen: false, modal: true, width: 800 });

    var data = null;
    if ($("#load").length != 0) {
        data = JSON.parse($("#load").val());
    }

    var mapElement = $("#map");

    var map = new mapFabric(mapElement, data != null ? data.controls : null);
    map.timeline = new timelineFabric(map, data != null ? data.timeline : null);

    if (data == null) {
        map.controller = new controllerFabric(map);
        $("#add").click(function () {
            $("#dialog").dialog('open');
        });

        $(".Hero").bind("click", function () {
            $(this).hide();

            new itemFabric(map, null, $(this).attr("heroId"), $(this).attr("src"), map.getCenter());

            $("#dialog").dialog('close')
        });

        $("#save").click(function () {
            if ($("#Author").val() == "") {
                alert("Назовись!");
                $("#Author").focus();
                return false;
            }

            if ($("#Comment").val() == "") {
                alert("Давай стратегию!");
                $("#Comment").focus();
                return false;
            }

            if ($("#Password").val() == "") {
                alert("Укажи пароль, он нужен для получения призов!");
                $("#Comment").focus();
                return false;
            }

            if (map.timeline.pack().length == 0) {
                alert("Нет ниодного действия.");                
                return false;
            }

            $("#Data").val(JSON.stringify({
                controls: map.pack(),
                timeline: map.timeline.pack()
            }));

            return true;
        });
    }
});
